package com.fire.eyes.service.device;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.fire.core.service.CkeckTokenService;
import com.fire.core.service.DBManagerService;
import com.fire.core.util.AjaxResult;
import com.fire.eyes.constants.ErrorCodeConstants;
import com.fire.eyes.model.*;
import com.fire.eyes.service.IAssetService;
import com.fire.eyes.service.IDeviceCategoryService;
import com.fire.eyes.service.IDeviceCategorySpecService;
import com.fire.eyes.service.ISiteService;
import com.fire.eyes.util.DateUtil;
import com.fire.eyes.validation.*;
import com.smartthing.rest.client.SmartThingClient;
import com.smartthing.rest.model.asset.AssetCategory;
import com.smartthing.rest.model.asset.HardwareAsset;
import com.smartthing.rest.model.asset.LocationAsset;
import com.smartthing.rest.model.asset.request.AssetCategoryCreateRequest;
import com.smartthing.rest.model.asset.request.HardwareAssetCreateRequest;
import com.smartthing.rest.model.device.Device;
import com.smartthing.rest.model.device.DeviceAssignment;
import com.smartthing.rest.model.device.DeviceSpecification;
import com.smartthing.rest.model.device.request.DeviceAssignmentCreateRequest;
import com.smartthing.rest.model.device.request.DeviceCreateRequest;
import com.smartthing.rest.model.device.request.DeviceSpecificationCreateRequest;
import com.smartthing.rest.model.search.DateRangeSearchCriteria;
import com.smartthing.rest.model.search.DeviceSearchResults;
import com.smartthing.spi.ISmartThingClient;
import com.smartthing.spi.SmartThingException;
import com.smartthing.spi.asset.AssetType;
import com.smartthing.spi.device.DeviceAssignmentType;
import com.smartthing.spi.device.DeviceContainerPolicy;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * @author yangxiaotian
 * @version 1.0
 * @date 2019/1/14 17:38
 * @description:设备处理逻辑
 */
@Service
public class DeviceService {
    private static Logger logger = Logger.getLogger(DeviceService.class);
    @Autowired
    private CkeckTokenService ckeckTokenService;
    @Autowired
    private ISiteService isSteService;
    @Autowired
    private IDeviceCategoryService deviceCategoryService;
    @Autowired
    private IDeviceCategorySpecService deviceCategorySpecService;
    @Autowired
    private DBManagerService dbManagerService;
    @Autowired
    private ISmartThingClient client;


    /**
     * @author yangxiaotian
     * @date ${DATE} ${TIME}
     * @description:创建设备
     */
    public AjaxResult creatDevices(AddDeviceReqDTO addDeviceReqDTO) throws SmartThingException {
//        TMitUserToken token = ckeckTokenService.ckeckToken(addDeviceReqDTO.getToken());
//        if (token == null) {
//            logger.error("错误为：无token记录");
//            return new AjaxResult(ErrorCodeConstants.PARAM_WRONGFULL, "无token记录", "无token记录");
//        }
//        ISmartThingClient client = new SmartThingClient("http://10.12.8.223:26666/smartthing/api/",
//                "admin", "password");
        CreatDeviceResp resp = new CreatDeviceResp();
        DeviceCreateRequest request = new DeviceCreateRequest();
        AjaxResult Ajaxresult = new AjaxResult();

        //查询设备是否有规格，如果有规格不用创建，
        DeviceCategorySpecModel model = new DeviceCategorySpecModel();
        /*String Specication = addDeviceReqDTO.getSpecication();
        if (StringUtils.isNotBlank(Specication)) {
            model.setSpectoken(addDeviceReqDTO.getSpecication());
        }else{
            Specication= UUID.randomUUID().toString();
        }*/
        model.setCategoryid(addDeviceReqDTO.getDevicecategoryid());
        model.setSiteid(addDeviceReqDTO.getSiteid());
        //查询设备规格分类表
        DeviceCategorySpecModel deviceCategorySpecModel = deviceCategorySpecService.selectOne(model);
        //查询传感器分类
        DeviceCategoryModel deviceCategoryModel = new DeviceCategoryModel();
        deviceCategoryModel.setCategoryid(addDeviceReqDTO.getDevicecategoryid());
        DeviceCategoryModel dvCategoryModel = deviceCategoryService.selectOne(deviceCategoryModel);
        //查询不到以categoryid和siteid为条件的数据，则新添加一条数据
        if (deviceCategorySpecModel == null) {
            //创建设备资产
            HardwareAssetCreateRequest reruest = new HardwareAssetCreateRequest();
            //设备分类表不为空
            if (dvCategoryModel != null) {
                reruest.setName(dvCategoryModel.getCategoryname() + "zichang");
            }
            String categoryId = "fs-devices";
            String assetsId = dbManagerService.getNextStringValue("assetsId");
            reruest.setId(assetsId);
            reruest.setImageUrl(addDeviceReqDTO.getImagesshot());
            reruest.setSku(addDeviceReqDTO.getDevicecategoryid());//sku先分类ID

            HardwareAsset hardwareAsset = null;
            try {
                hardwareAsset = client.creatHardwareAsset(categoryId, reruest);
            } catch (SmartThingException e) {
                e.printStackTrace();
                Ajaxresult.setMessage("创建设备时，添加设备资产返回错误信息" + e.getMessage());
                Ajaxresult.setTips("添加设备时创建资产失败");
                Ajaxresult.setStatus("1");
                return Ajaxresult;
            }
            logger.info("创建设备资产结束");

            //设备资产创建成功创建规格
            if (hardwareAsset != null) {
                //没有规格，创建规格
                DeviceSpecificationCreateRequest specificationRequest = new DeviceSpecificationCreateRequest();
                specificationRequest.setAssetId(assetsId);
                specificationRequest.setAssetModuleId("fs-devices");//设备规格先写死
                specificationRequest.setName(dvCategoryModel.getCategoryname() + "guige");
                // Specication = "343433";
                //生成Specication
                String Specication= UUID.randomUUID().toString();
                specificationRequest.setToken(Specication);//规格token........需要判断
                specificationRequest.setContainerPolicy(DeviceContainerPolicy.Standalone);

                DeviceSpecification deviceSpecification = null;
                try {
                    deviceSpecification = client.createDeviceSpecification(specificationRequest);
                } catch (SmartThingException e) {
                    e.printStackTrace();
                    Ajaxresult.setMessage("创建设备时，添加规格返回的错误消息" + e.getMessage());
                    Ajaxresult.setTips("添加设备时创建规格失败");
                    Ajaxresult.setStatus("1");
                    return Ajaxresult;

                }
                String assId = deviceSpecification.getAssetId();
                if (StringUtils.isNotBlank(assId)) {//创建规格成功更新本地库
                    model.setCategoryid(addDeviceReqDTO.getDevicecategoryid());
                    model.setCreatetime(DateUtil.dateToString(DateUtil.getCurrentDateTime(), "yyyy-MM-dd"));
                    model.setSiteid(addDeviceReqDTO.getSiteid());
                    model.setSpectoken(Specication);
                    boolean falg = deviceCategorySpecService.insert(model);
                    if (falg) {
                        request.setSpecificationToken(Specication);
                    }
                }
            }
        } else {
            request.setSpecificationToken(deviceCategorySpecModel.getSpectoken());
        }

        //创建主设备信息
        request.setComments(dvCategoryModel.getDescriptor());
        request.setHardwareId(addDeviceReqDTO.getDeviceid());//硬件id
        Map<String, String> metadata = new HashMap<String, String>();
        metadata.put("categoryid", dvCategoryModel.getCategoryid());
        metadata.put("categoryname", dvCategoryModel.getCategoryname());
        metadata.put("location", addDeviceReqDTO.getLocation());
        Integer level = dvCategoryModel.getLevel();
        String range = "";
        switch (level){
            case 0:
                range = "unknown";
                break;
            case 1:
                range = "water";
                break;
            case 2:
                range = "electricity";
                break;
            case 3:
                range = "gas";
                break;
            case 4:
                range = "fire";
                break;
            case 5:
                range = "dvr";
                break;
        }
        metadata.put("range", range);
        request.setMetadata(metadata);
        request.setRemoveParentHardwareId(false);
        request.setSiteToken(addDeviceReqDTO.getSiteid());//站点token
        request.setStatus("1");
        JSONObject json = (JSONObject) JSON.toJSON(request);
        System.out.println("拼接都设备消息" + json);

        Device devices = null;
        try {
            devices = client.createDevice(request);
        } catch (SmartThingException e) {
            e.printStackTrace();
            Ajaxresult.setMessage("创建设备返回的错误消息" + e.getMessage());
            Ajaxresult.setStatus("1");
            Ajaxresult.setTips("创建设备失败");
            return Ajaxresult;
        }
        logger.info("获取到的信息" + devices);
        if (devices != null) {
            //创建成功返回前台
            resp.setAssetid(devices.getSpecification().getAssetId());
            resp.setAssetidName(devices.getSpecification().getAssetName());
            resp.setDeviceid(devices.getHardwareId());
            resp.setDevicename(devices.getSpecification().getName());
            resp.setImagesshot(devices.getSpecification().getAssetImageUrl());
            resp.setLocation(addDeviceReqDTO.getLocation());
            resp.setOperator("");//操作者...需要从token中获取，add token
            resp.setSiteid(devices.getSiteToken());
            Ajaxresult.setContext(resp);
            Ajaxresult.setStatus("0");
            Ajaxresult.setMessage("创建设备成功");
            Ajaxresult.setTips("创建设备成功");
        } else {
            Ajaxresult.setStatus("1");
            Ajaxresult.setMessage("创建设备失败");
            Ajaxresult.setTips("创建设备失败");
        }

        return Ajaxresult;
    }

    /**
     * @author yangxiaotian
     * @date ${DATE} ${TIME}
     * @description:根据站点查询设备
     */
    public AjaxResult queryDevicesList(SiteIdDTO siteIdDTO) throws SmartThingException {
//        TMitUserToken token = ckeckTokenService.ckeckToken(siteIdDTO.getToken());
//        if (token == null) {
//           logger.error("错误为：无token记录");
//            return new AjaxResult(ErrorCodeConstants.PARAM_WRONGFULL, "无token记录", "无token记录");
//        }
        //查询站点
        AjaxResult Ajaxresult = new AjaxResult();
        SiteModel site = isSteService.selectById(siteIdDTO.getSiteid());
        if (site == null) {
            return new AjaxResult(ErrorCodeConstants.NO_SITE, "无此站点", "请核对您的站点");
        }
        String siteToken = site.getSitetoken();
        if (StringUtils.isBlank(siteToken)) {
            return new AjaxResult(ErrorCodeConstants.NO_SITE, "无此站点", "请核对您的站点");
        }
        //请求smartthing
//        ISmartThingClient client = new SmartThingClient("http://10.12.8.223:26666/smartthing/api/",
//                "admin", "password");
        DateRangeSearchCriteria criteria = new DateRangeSearchCriteria(siteIdDTO.getPage(), siteIdDTO.getPagesize(), null, null);
        boolean includeDeleted = false;
        boolean excludeAssigned = false;
        boolean populateSpecification = false;
        boolean populateAssignment = false;
        DeviceSearchResults result = null;
        try {
            result = client.listDevices(siteToken, includeDeleted, excludeAssigned,
                    populateSpecification, populateAssignment, criteria);
        } catch (SmartThingException e) {
            e.printStackTrace();
            Ajaxresult.setTips("查询设备列表失败");
            Ajaxresult.setMessage("smartthing查询设备列表失败返回的错误消息" + e.getMessage());
            Ajaxresult.setStatus("1");
            return Ajaxresult;

        }
        logger.info("获取到的返回消息数" + result.getNumResults());
        long nums = result.getNumResults();
        List<GetdevicesResp> devicelist = new ArrayList<GetdevicesResp>();
        if (nums > 0) {
            List<Device> list = result.getResults();
            for (Device device : list) {
                GetdevicesResp resp = new GetdevicesResp();
                logger.info("获取到的是设备" + device.getMetadata("categoryid"));
                resp.setCategoryid(device.getMetadata("categoryid"));
                resp.setCategoryname(device.getMetadata("categoryname"));
                resp.setCreatetime(DateUtil.dateToString(device.getCreatedDate(), "yyyy-MM-dd"));
                resp.setDeviceid(device.getHardwareId());
                resp.setDevicekurl(device.getAssetImageUrl());
                resp.setDevicename(device.getAssetName());
                resp.setSpectoken(device.getSpecificationToken());
                resp.setAssigntoken(device.getAssignmentToken());
                devicelist.add(resp);

            }
            Ajaxresult.setContext(devicelist);
            Ajaxresult.setMessage("查询设备列表成功");
            Ajaxresult.setStatus("0");
            Ajaxresult.setTips("查询设备列表成功");
        } else {
            Ajaxresult.setMessage("查询设备列表失败");
            Ajaxresult.setStatus("1");
            Ajaxresult.setTips("查询设备列表失败");
        }
        return Ajaxresult;

    }

    /**
     * @author yangxiaotian
     * @date ${DATE} ${TIME}
     * @description:查询设备品类
     */
    public AjaxResult queryDeviceCategory(TokenDTO tokenDTO) {
//        TMitUserToken token = ckeckTokenService.ckeckToken(tokenDTO.getToken());
//        if (token == null) {
//            logger.error("错误为：无token记录");
//            return new AjaxResult(ErrorCodeConstants.PARAM_WRONGFULL, "无token记录", "无token记录");
//        }
        Page<DeviceCategoryModel> page = new Page(tokenDTO.getPage(), tokenDTO.getPagesize());
        Wrapper<DeviceCategoryModel> wrapper = new EntityWrapper<>();
        Page<DeviceCategoryModel> deviceCategor = deviceCategoryService.selectPage(page, wrapper);
        List<DeviceCategoryModel> deviceList = null;
        if (deviceCategor != null) {
            deviceList = deviceCategor.getRecords();

        }
        AjaxResult Ajaxresult = new AjaxResult();
        List<DeviceCategoryResp> list = new ArrayList<DeviceCategoryResp>();
        if (deviceList.size() > 0) {
            for (DeviceCategoryModel deviceCategory : deviceList) {
                DeviceCategoryResp resp = new DeviceCategoryResp();
                resp.setDevicecategoryid(deviceCategory.getCategoryid());
                resp.setDevicecategoryname(deviceCategory.getCategoryname());
                resp.setDevicecategoryurl(deviceCategory.getCategoryurl());
                list.add(resp);
            }
        } else {
            Ajaxresult.setMessage("查询设备品类失败");
            Ajaxresult.setStatus("1");
            Ajaxresult.setTips("查询设备品类失败");
        }
        Ajaxresult.setContext(list);
        Ajaxresult.setMessage("查询设备品类成功");
        Ajaxresult.setStatus("0");
        Ajaxresult.setTips("查询设备品类成功");
        return Ajaxresult;

    }

    /**
     * @author yangxiaotian
     * @date ${DATE} ${TIME}
     * @description:根据设备id 查询传感器详情
     */
    public AjaxResult queryDeviceByid(DeviceIdDTO deviceIdDTO) throws SmartThingException {
//        TMitUserToken token = ckeckTokenService.ckeckToken(deviceIdDTO.getToken());
//        if (token == null) {
//            logger.error("错误为：无token记录");
//            return new AjaxResult(ErrorCodeConstants.PARAM_WRONGFULL, "无token记录", "无token记录");
//        }
        AjaxResult Ajaxresult = new AjaxResult();
//        ISmartThingClient client = new SmartThingClient("http://10.12.8.223:26666/smartthing/api/",
//                "admin", "password");
        Device device = null;
        try {
            device = client.getDeviceByHardwareId(deviceIdDTO.getDeviceid());
        } catch (SmartThingException e) {
            e.printStackTrace();
            Ajaxresult.setMessage("smartthing返回的异常消息" + e.getMessage());
            Ajaxresult.setStatus("1");
            Ajaxresult.setTips("查询设备详情失败");
            //throw new SmartThingException("smartthing返回的异常消息"+e.getMessage());
            return Ajaxresult;
        }
        if (device != null) {
            GetdeviceDetailResp resp = new GetdeviceDetailResp();
            resp.setDevicename(device.getSpecification().getAssetName());
            resp.setCategoryid(device.getMetadata("categoryid"));
            resp.setDeviceid(device.getHardwareId());
            resp.setCategoryname(device.getMetadata("categoryname"));
            resp.setDevicekurl(device.getSpecification().getAssetImageUrl());
            resp.setCreatetime(DateUtil.dateToString(device.getCreatedDate(), "yyyy-MM-dd"));
            resp.setFixlocation(device.getMetadata("location"));
            if(device.getAssignment()!=null){
                resp.setAssetid(device.getAssignment().getAssetId());
                resp.setAssetname(device.getAssignment().getAssetName());
                resp.setAssigntoken(device.getAssignment().getToken());
            }
            resp.setSpectoken(device.getSpecification().getToken());
            Ajaxresult.setContext(resp);
            Ajaxresult.setMessage("查询设备详情成功");
            Ajaxresult.setStatus("0");
            Ajaxresult.setTips("查询设备详情成功");
        } else {
            Ajaxresult.setMessage("查询设备详情失败");
            Ajaxresult.setStatus("1");
            Ajaxresult.setTips("查询设备详情失败");
        }

        return Ajaxresult;

    }

    /**
     * @author yangxiaotian
     * @date ${DATE} ${TIME}
     * @description:创建设备关联
     */
    public AjaxResult CreatDeviceAssignments(CreatDeviceAssignmentsDTO creatDeviceAssignmentsDTO) throws SmartThingException {
//        TMitUserToken token = ckeckTokenService.ckeckToken(creatDeviceAssignmentsDTO.getToken());
//        if (token == null) {
//            logger.error("错误为：无token记录");
//            return new AjaxResult(ErrorCodeConstants.PARAM_WRONGFULL, "无token记录", "无token记录");
//        }
        AjaxResult ajaxResult = new AjaxResult();
        GreatDeviceAssignmentsResp resp = new GreatDeviceAssignmentsResp();
//        ISmartThingClient client = new SmartThingClient("http://10.12.8.223:26666/smartthing/api/",
//                "admin", "password");
        DeviceAssignmentCreateRequest request = new DeviceAssignmentCreateRequest();
        request.setToken(UUID.randomUUID().toString());//创建管理token,后面需要生成
        request.setDeviceHardwareId(creatDeviceAssignmentsDTO.getDeviceid());
        request.setAssignmentType(DeviceAssignmentType.Associated);
        request.setAssetModuleId("localtion@"+creatDeviceAssignmentsDTO.getSiteid());
        request.setAssetId(creatDeviceAssignmentsDTO.getAssetid());

        //查询并取出device的元数据放入assignment的元数据
        String hardwareId = creatDeviceAssignmentsDTO.getDeviceid();
        Device device = null;
        try {
            device = client.getDeviceByHardwareId(hardwareId);
        } catch (SmartThingException e) {
            e.printStackTrace();
            ajaxResult.setMessage("smartthing返回的异常消息" + e.getMessage());
            ajaxResult.setStatus("1");
            ajaxResult.setTips("获取设备信息失败");
            return ajaxResult;
        }
        Map<String, String> deviceMetadata = device.getMetadata();
        //查询并取出Asset的元数据的location放入assignment的元数据
        String categoryId = checkCategory(device.getSiteToken());
        LocationAsset locationAssetDetails = client.getLocationAssetDetails(categoryId, creatDeviceAssignmentsDTO.getAssetid());
        if (locationAssetDetails!=null){
            Map<String, String> properties = locationAssetDetails.getProperties();
            deviceMetadata.put("siteName",device.getSite().getName());
            deviceMetadata.put("assetName",locationAssetDetails.getName());
            deviceMetadata.put("Alocation",properties.get("Alocation"));
            deviceMetadata.put("Arange",properties.get("Arange"));
            request.setMetadata(deviceMetadata);
        }

        DeviceAssignment deviceAssignment = null;
        try {
            deviceAssignment = client.createDeviceAssignment(request);
        } catch (SmartThingException e) {
            e.printStackTrace();
            ajaxResult.setMessage("smartthing返回的异常消息" + e.getMessage());
            ajaxResult.setStatus("1");
            ajaxResult.setTips("创建设备关联失败");
            return ajaxResult;
        }
        if (deviceAssignment != null) {
            resp.setAssigntoken("33435657");
            resp.setCreatetime(DateUtil.dateToString(DateUtil.getCurrentDateTime(), "yyyy-MM-dd"));
            ajaxResult.setTips("创建关联成功了");
            ajaxResult.setMessage("创建关联成功了");
            ajaxResult.setStatus("0");
            ajaxResult.setContext(resp);
        } else {
            ajaxResult.setTips("创建关联失败");
            ajaxResult.setMessage("创建关联失败");
            ajaxResult.setStatus("1");
        }

        return ajaxResult;

    }

    public String checkCategory(String siteid) throws SmartThingException{

        String categoryId = "localtion@" + siteid;
        AssetCategory category = client.getCatrgory(categoryId);
        if (category != null){
            return category.getId();
        }

        AssetCategoryCreateRequest request = new AssetCategoryCreateRequest();
        request.setId(categoryId);
        request.setName("location@" + System.currentTimeMillis());
        request.setAssetType(AssetType.Location);
        AssetCategory assetCategory = client.creatAssetsCategories(request);
        return assetCategory.getId();
    }
    public static void main(String[] args) throws SmartThingException {

    }

}
